/*
 * Copyright (C) 2010 TopCoder Inc., All Rights Reserved.
 */
package com.hercules.android.receiver.entities;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.graphics.Matrix;

import com.hercules.android.receiver.ReceiverUtil;
import com.hercules.android.receiver.XREObjectFormatterException;

/**
 * <p>
 * A POJO contains the data of XREView resource.
 * </p>
 * 
 * @author TCSASSEMBER
 * @version 1.0
 */
public class XREView extends XREObject {
    /**
     * The ID of the parent view.
     */
    private Integer parent;

    /**
     * A value between 0 and 1 that dictates the view's opacity level.
     */
    private Double alpha;

    /**
     * An application-defined string that can be used to identify the view on
     * the hierarchy.
     */
    private String name;

    /**
     * An array of exactly two elements that specifies the view's height and
     * width.
     */
    private Integer[] dimensions;

    /**
     * The view's transformation matrix.
     */
    private float[] matrix;

    /**
     * Indicates whether the view will clip the child views whose dimensions
     * exceed the dimensions of this view.
     */
    private Boolean clip;

    /**
     * The ID of the resource associated with this view.
     */
    private Integer resource;

    /**
     * A hash containing the desired resource options to use for the association
     * between this view and its resource.
     */
    private HashMap<String, String> resourceOptions;

    /**
     * The ID of the mask associated with this view.
     */
    private Integer mask;

    /**
     * Indicates whether the receiver should ignore mouse events that are
     * generated by this view.
     */
    private Boolean ignoreMouse;

    /**
     * Indicates whether the view is visible.
     */
    private Boolean visible;

    /**
     * Indicates whether modifications to this view, its children or any
     * resources applied to them should be reflected on screen.
     */
    private Boolean painting;

    /**
     * Represents the children view.
     */
    private List<XREView> children;

    /**
     * Default constructor. Set the default values.
     */
    public XREView() {
        super();
        alpha = 1.0;
        name = "";
        dimensions = new Integer[] { 300, 300 };
        matrix = new float[9];
        new Matrix().getValues(matrix);
        clip = false;
        resource = 0;
        resourceOptions = new HashMap<String, String>();
        mask = 0;
        ignoreMouse = false;
        visible = true;
        painting = true;
        children = new ArrayList<XREView>();
    }

    /**
     * Gets the ID of the parent view.
     * 
     * @return ID of the parent view.
     */
    public Integer getParent() {
        return parent;
    }

    /**
     * Sets the ID of the parent view.
     * 
     * @param parent
     *            ID of the parent view.
     */
    public void setParent(Integer parent) {
        this.parent = parent;
    }

    /**
     * Gets the view's alpha value.
     * 
     * @return the view's alpha value.
     */
    public Double getAlpha() {
        return alpha;
    }

    /**
     * Sets the view's alpha value.
     * 
     * @param alpha
     *            the view's alpha value.
     */
    public void setAlpha(Double alpha) {
        this.alpha = alpha;
    }

    /**
     * Gets the view's name.
     * 
     * @return the view's name
     */
    public String getName() {
        return name;
    }

    /**
     * Sets the view's name.
     * 
     * @param name
     *            the view's name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Gets the view's dimensions.
     * 
     * @return the view's dimensions.
     */
    public Integer[] getDimensions() {
        return dimensions;
    }

    /**
     * Sets the view's dimensions.
     * 
     * @param dimensions
     *            the view's dimensions.
     */
    public void setDimensions(Integer[] dimensions) {
        this.dimensions = dimensions;
    }

    /**
     * Gets the matrix of the view.
     * 
     * @return the matrix of the view.
     */
    public float[] getMatrix() {
        return matrix;
    }

    /**
     * Sets the matrix of the view.
     * 
     * @param matrix
     *            the matrix of the view.
     */
    public void setMatrix(float[] matrix) {
        this.matrix = matrix;
    }

    /**
     * Gets whether to clip the view.
     * 
     * @return a flag indicates whether to clip the view.
     */
    public Boolean getClip() {
        return clip;
    }

    /**
     * Sets whether to clip the view.
     * 
     * @param clip
     *            a flag indicates whether to clip the view.
     */
    public void setClip(Boolean clip) {
        this.clip = clip;
    }

    /**
     * Gets the ID of the resource associated with this view.
     * 
     * @return the ID of the resource associated with this view.
     */
    public Integer getResource() {
        return resource;
    }

    /**
     * Sets the ID of the resource associated with this view.
     * 
     * @param resource
     *            the ID of the resource associated with this view.
     */
    public void setResource(Integer resource) {
        this.resource = resource;
    }

    /**
     * Gets the desired resource options to use for the association between this
     * view and its resource.
     * 
     * @return the desired resource options to use for the association between
     *         this view and its resource.
     */
    public HashMap<String, String> getResourceOptions() {
        return resourceOptions;
    }

    /**
     * Sets the desired resource options to use for the association between this
     * view and its resource.
     * 
     * @param resourceOptions
     *            the desired resource options to use for the association
     *            between this view and its resource.
     */
    public void setResourceOptions(HashMap<String, String> resourceOptions) {
        this.resourceOptions = resourceOptions;
    }

    /**
     * Gets the ID of the mask associated with this view.
     * 
     * @return the ID of the mask associated with this view.
     */
    public Integer getMask() {
        return mask;
    }

    /**
     * Sets the ID of the mask associated with this view.
     * 
     * @param mask
     *            the ID of the mask associated with this view.
     */
    public void setMask(Integer mask) {
        this.mask = mask;
    }

    /**
     * Gets whether the receiver should ignore mouse events that are generated
     * by this view.
     * 
     * @return a flag indicates whether the receiver should ignore mouse events
     *         that are generated by this view.
     */
    public Boolean getIgnoreMouse() {
        return ignoreMouse;
    }

    /**
     * Sets whether the receiver should ignore mouse events that are generated
     * by this view.
     * 
     * @param ignoreMouse
     *            a flag indicates whether the receiver should ignore mouse
     *            events that are generated by this view.
     */
    public void setIgnoreMouse(Boolean ignoreMouse) {
        this.ignoreMouse = ignoreMouse;
    }

    /**
     * Gets whether the view is visible.
     * 
     * @return whether the view is visible.
     */
    public Boolean getVisible() {
        return visible;
    }

    /**
     * Sets whether the view is visible.
     * 
     * @param visible
     *            whether the view is visible.
     */
    public void setVisible(Boolean visible) {
        this.visible = visible;
    }

    /**
     * Gets whether modifications to this view, its children or any resources
     * applied to them should be reflected on screen.
     * 
     * @return whether modifications to this view, its children or any resources
     *         applied to them should be reflected on screen.
     */
    public Boolean getPainting() {
        return painting;
    }

    /**
     * Sets whether modifications to this view, its children or any resources
     * applied to them should be reflected on screen.
     * 
     * @param painting
     *            whether modifications to this view, its children or any
     *            resources applied to them should be reflected on screen.
     */
    public void setPainting(Boolean painting) {
        this.painting = painting;
    }

    /**
     * Gets the children views.
     * 
     * @return the children views
     */
    public List<XREView> getChildren() {
        return children;
    }

    /**
     * Sets the children views.
     * 
     * @param children
     *            the children views
     */
    public void setChildren(List<XREView> children) {
        this.children = children;
    }

    /**
     * Set properties from <code>JSONObject</code>.
     * 
     * @param json
     *            the <code>JSONObject</code> instance
     * @throws XREObjectFormatterException
     *             if any error occurs
     */
    public void setProperties(JSONObject json) throws XREObjectFormatterException {
        super.setProperties(json);
        try {
            if (json.has("params")) {
                json = json.getJSONObject("params");
                if (json.has("dimensions")) {
                    Integer[] dimensions = new Integer[2];
                    JSONArray array = json.getJSONArray("dimensions");
                    dimensions[0] = array.getInt(0);
                    dimensions[1] = array.getInt(1);
                    this.setDimensions(dimensions);
                }
                if (json.has("matrix")) {
                    Double[] matrix = new Double[16];
                    JSONArray array = json.getJSONArray("matrix");
                    for (int i = 0; i < 16; i++) {
                        matrix[i] = array.getDouble(i);
                    }
                    this.setMatrix(ReceiverUtil.getAndroidMatrix(matrix));
                }
            }
        } catch (JSONException e) {
            throw new XREObjectFormatterException("Error occurs when reading from JSON object.", e);
        }
    }

}
